<template>
  <h3>多币种汇率走势</h3>
  <el-form :inline="true" :model="formInline" class="demo-form-inline">
    <el-form-item label="日期范围">
      <el-config-provider :locale="locale">
        <el-date-picker
            v-model="formInline.dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="YYYY-MM-DD"
            :default-time="defaultTime"
            format="YYYY年MM月DD日"
            :shortcuts="shortcuts"
            :first-day-of-week="1"
            :locale="locale"
            @change="handleDateChange"
            clearable
        />
      </el-config-provider>
    </el-form-item>

    <el-form-item label="翻转汇率">
      <el-switch
          v-model="formInline.isChangeCode"
          @change="handleChangeCodeSwitch"
      />
    </el-form-item>

    <el-form-item label="其他汇率范围">
      <el-input-number
          v-model="formInline.otherMin"
          :precision="4"
          :step="0.1"
          placeholder="最小值"
          size="small"
          style="width: 120px; margin-right: 10px"
          @change="handleRangeChange"
      />
      <el-input-number
          v-model="formInline.otherMax"
          :precision="4"
          :step="0.1"
          placeholder="最大值"
          size="small"
          style="width: 120px"
          @change="handleRangeChange"
      />
    </el-form-item>
  </el-form>
  <div ref="chartRef" style="width: 100%; height: 1200px"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, reactive, watch } from "vue";
import type { DateModelType } from 'element-plus'
import type { Language } from 'element-plus/es/locale'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import axios from "axios";
import * as echarts from "echarts";

interface CurrencyData {
  max: number;
  min: number;
  rates: {
    [date: string]: number;
  };
}

interface ApiResponse {
  code: number;
  data: {
    [currency: string]: CurrencyData;
  };
  msg: string;
}

export default defineComponent({
  name: "DateRate",
  setup() {
    const chartRef = ref<HTMLElement>();
    let myChart: echarts.ECharts | null = null;
    const locale = ref<Language>(zhCn)
    const chartData = ref<ApiResponse['data'] | null>(null);

    const formInline = reactive({
      dateRange: null as [string, string] | null,
      isChangeCode: false,
      otherMin: undefined as number | undefined,
      otherMax: undefined as number | undefined
    })

    // 设置默认时间
    const defaultTime = [
      new Date(2000, 1, 1, 0, 0, 0),
      new Date(2000, 1, 1, 23, 59, 59)
    ]

    // 快捷选项
    const shortcuts = [
      {
        text: '最近一周',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
          return [start, end]
        },
      },
      {
        text: '最近一个月',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setMonth(start.getMonth() - 1)
          return [start, end]
        },
      },
      {
        text: '最近三个月',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setMonth(start.getMonth() - 3)
          return [start, end]
        },
      },
    ]

    const initChart = (data: ApiResponse['data']) => {
      if (!chartRef.value) return;

      if (myChart) {
        myChart.dispose();
      }

      myChart = echarts.init(chartRef.value);
      chartData.value = data;

      // 分离JPY、HKD和其他币种
      const currencies = Object.keys(data);
      const dates = Object.keys(data[currencies[0]].rates).sort();
      const otherCurrencies = currencies.filter(c => c !== 'JPY' && c !== 'HKD');

      // 计算其他币种的最大最小值
      let otherMin = formInline.otherMin;
      let otherMax = formInline.otherMax;
      if (otherMin === undefined || otherMax === undefined) {
        const otherValues = otherCurrencies.flatMap(currency =>
            Object.values(data[currency].rates)
        );
        otherMin = Math.min(...otherValues);
        otherMax = Math.max(...otherValues);
        formInline.otherMin = otherMin;
        formInline.otherMax = otherMax;
      }

      const option = {
        title: [
          {
            text: "日元(JPY)汇率走势图",
            left: 'center',
            top: 0,
            textStyle: {
              fontSize: 16
            }
          },
          {
            text: "港币(HKD)汇率走势图",
            left: 'center',
            top: '33%',
            textStyle: {
              fontSize: 16
            }
          },
          {
            text: "其他币种汇率走势图",
            left: 'center',
            top: '66%',
            textStyle: {
              fontSize: 16
            }
          }
        ],
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "cross",
          },
        },
        grid: [
          {
            left: '10%',
            right: '10%',
            top: '10%',
            height: '23%',
            containLabel: true
          },
          {
            left: '10%',
            right: '10%',
            top: '43%',
            height: '23%',
            containLabel: true
          },
          {
            left: '10%',
            right: '10%',
            top: '76%',
            height: '23%',
            containLabel: true
          }
        ],
        legend: [
          {
            data: ['JPY'],
            top: '5%',
            left: 'right'
          },
          {
            data: ['HKD'],
            top: '38%',
            left: 'right'
          },
          {
            data: otherCurrencies,
            top: '71%',
            type: 'scroll',
            left: 'right'
          }
        ],
        xAxis: [
          {
            type: "category",
            gridIndex: 0,
            data: dates,
            axisLabel: {
              rotate: 45,
              fontSize: 12
            }
          },
          {
            type: "category",
            gridIndex: 1,
            data: dates,
            axisLabel: {
              rotate: 45,
              fontSize: 12
            }
          },
          {
            type: "category",
            gridIndex: 2,
            data: dates,
            axisLabel: {
              rotate: 45,
              fontSize: 12
            }
          }
        ],
        yAxis: [
          {
            type: "value",
            gridIndex: 0,
            name: "JPY汇率",
            min: data['JPY'].min,
            max: data['JPY'].max,
            nameTextStyle: {
              fontSize: 12
            },
            axisLabel: {
              formatter: "{value}",
              fontSize: 12
            },
            splitLine: {
              show: true
            }
          },
          {
            type: "value",
            gridIndex: 1,
            name: "HKD汇率",
            min: data['HKD'].min,
            max: data['HKD'].max,
            nameTextStyle: {
              fontSize: 12
            },
            axisLabel: {
              formatter: "{value}",
              fontSize: 12
            },
            splitLine: {
              show: true
            }
          },
          {
            type: "value",
            gridIndex: 2,
            name: "其他币种汇率",
            min: otherMin,
            max: otherMax,
            nameTextStyle: {
              fontSize: 12
            },
            axisLabel: {
              formatter: "{value}",
              fontSize: 12
            },
            splitLine: {
              show: true
            }
          }
        ],
        dataZoom: [
          {
            type: "slider",
            show: true,
            xAxisIndex: 0,
            start: 0,
            end: 100,
            top: '33%'
          },
          {
            type: "inside",
            xAxisIndex: 0,
            start: 0,
            end: 100
          },
          {
            type: "slider",
            show: true,
            xAxisIndex: 1,
            start: 0,
            end: 100,
            top: '66%'
          },
          {
            type: "inside",
            xAxisIndex: 1,
            start: 0,
            end: 100
          },
          {
            type: "slider",
            show: true,
            xAxisIndex: 2,
            start: 0,
            end: 100,
            bottom: '3%'
          },
          {
            type: "inside",
            xAxisIndex: 2,
            start: 0,
            end: 100
          }
        ],
        series: [
          // JPY数据系列
          {
            name: 'JPY',
            type: "line",
            xAxisIndex: 0,
            yAxisIndex: 0,
            data: dates.map(date => data['JPY'].rates[date]),
            smooth: true,
            symbol: "circle",
            symbolSize: 6,
            markPoint: {
              data: [
                { type: "max", name: "最大值" },
                { type: "min", name: "最小值" }
              ]
            }
          },
          // HKD数据系列
          {
            name: 'HKD',
            type: "line",
            xAxisIndex: 1,
            yAxisIndex: 1,
            data: dates.map(date => data['HKD'].rates[date]),
            smooth: true,
            symbol: "circle",
            symbolSize: 6,
            markPoint: {
              data: [
                { type: "max", name: "最大值" },
                { type: "min", name: "最小值" }
              ]
            }
          },
          // 其他币种数据系列
          ...otherCurrencies.map(currency => ({
            name: currency,
            type: "line",
            xAxisIndex: 2,
            yAxisIndex: 2,
            data: dates.map(date => data[currency].rates[date]),
            smooth: true,
            symbol: "circle",
            symbolSize: 6,
            markPoint: {
              data: [
                { type: "max", name: "最大值" },
                { type: "min", name: "最小值" }
              ]
            }
          }))
        ]
      };

      myChart.setOption(option);

      // 响应式调整
      window.addEventListener("resize", () => {
        myChart?.resize();
      });
    };

    const fetchRateData = async () => {
      if (!formInline.dateRange) return;

      try {
        const [startDate, endDate] = formInline.dateRange;
        const response = await axios.get<ApiResponse>("api/rate/rate_date_rate", {
          params: {
            start_date: startDate,
            end_date: endDate,
            change_code: formInline.isChangeCode ? "1" : ""
          },
        });
        if (response.data.code === 200) {
          initChart(response.data.data);
        }
      } catch (error) {
        console.error("获取汇率数据失败:", error);
      }
    };

    const handleDateChange = (val: DateModelType) => {
      if (val) {
        fetchRateData();
      }
    };

    const handleChangeCodeSwitch = () => {
      if (formInline.dateRange) {
        fetchRateData();
      }
    };

    const handleRangeChange = () => {
      if (chartData.value) {
        initChart(chartData.value);
      }
    };

    // 获取默认日期范围
    const getDefaultDateRange = () => {
      const end = new Date()
      const start = new Date()
      start.setMonth(start.getMonth() - 1)

      const formatDate = (date: Date) => {
        return date.toISOString().slice(0, 10)
      }

      return [formatDate(start), formatDate(end)]
    }

    onMounted(() => {
      formInline.dateRange = getDefaultDateRange();
      fetchRateData();
    });

    return {
      chartRef,
      formInline,
      defaultTime,
      shortcuts,
      handleDateChange,
      handleChangeCodeSwitch,
      handleRangeChange,
      locale,
    };
  },
});
</script>

<style>
.demo-form-inline .el-select {
  --el-select-width: 220px;
}

.demo-form-inline .el-date-editor--daterange {
  --el-date-editor-width: 360px;
}
</style>
